package com.neusoft.bizcore.auth.controller;

import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.auth.common.jwt.JwtAuthProvider;
import com.neusoft.bizcore.auth.dto.DingConfigDTO;
import com.neusoft.bizcore.auth.model.DingUser;
import com.neusoft.bizcore.auth.repository.DingUserRepository;
import com.neusoft.bizcore.auth.service.AuthUserService;
import com.neusoft.bizcore.auth.service.DingDingService;
import com.neusoft.bizcore.web.dto.result.ResultDTO;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api("钉钉对接管理")
@RestController
@RequestMapping(value = "/api/w/auth/dingding")
public class DingDingController {

    @Autowired
    private DingDingService dingDingService;
    @Autowired
    private DingUserRepository dingUserRepository;
    @Autowired
    private AuthUserService authUserService;

    @ApiOperation("获取钉钉应用配置信息")
    @GetMapping
    public ResultDTO<?> getConfig() {
        final DingConfigDTO dto = this.dingDingService.getDingConfig();
        if (null == dto) {
            return ResultDTO.failure();
        }
        return ResultDTO.success(dto);
    }

    @ApiOperation("创建钉钉应用配置信息")
    @PostMapping
    public ResultDTO<DingConfigDTO> create(@RequestBody final DingConfigDTO dto) {
        final DingConfigDTO result = this.dingDingService.setDingConfig(dto);
        return ResultDTO.success(result);
    }

    @ApiOperation(value = "修改钉钉应用配置信息")
    @PutMapping("/{id}")
    public ResultDTO<DingConfigDTO> update(@PathVariable final Long id,
            @RequestBody final DingConfigDTO dto) {
        dto.setId(id);
        final DingConfigDTO result = this.dingDingService.setDingConfig(dto);
        return ResultDTO.success(result);
    }

    @ApiOperation("删除钉钉应用配置信息")
    @DeleteMapping("/{id}")
    public ResultDTO<Void> delete(@PathVariable final Long id) {
        this.dingDingService.delete(id);
        return ResultDTO.success();
    }

    /**
     * https://ding-doc.dingtalk.com/document#/org-dev-guide/logon-free-process
     *
     * @param authCode
     * @return
     */
    @PostMapping("/login")
    public ResultDTO<?> login(@RequestParam final String authCode) {
        final String userId = this.dingDingService.getDingUserIdByAuthCode(authCode);
        if (null == userId) {
            return ResultDTO.failure("invalidauthcode");
        }

        final DingUser dingUser = this.dingUserRepository.findByDingUserId(userId);
        if (null == dingUser) {
            // 前台需跳转至用户绑定界面
            return ResultDTO.failure("unbinddinguser");
        }

        final JwtAuthProvider jwtAuthProvider = new JwtAuthProvider(1000 * 24 * 60 * 60 * 1000, "secret");
        final String token = jwtAuthProvider.generateToken(dingUser.getUser().getUsername(),
                dingUser.getUser().getRoles().stream().map(b -> b.getCode()).collect(Collectors.toList()));

        return ResultDTO.success(token);
    }

    @PostMapping("/bind")
    public ResultDTO<?> bind(@RequestParam final Map<String, Object> params) {
        if (!params.containsKey("authCode")) {
            return ResultDTO.failure("缺少参数authCode");
        }
        final String authCode = (String) params.get("authCode");

        if (!params.containsKey("username") || !params.containsKey("password")) {
            return ResultDTO.failure("参数不合法");
        }

        final UserBean userBean = this.authUserService.loadUserByUsername((String) params.get("username"));

        if (null == userBean) {
            return ResultDTO.failure("用户名不存在");
        }

        if (!userBean.getPassword().equals(DigestUtils.md5DigestAsHex(((String) params.get("password")).getBytes()))) {
            return ResultDTO.failure("密码不正确");
        }

        final String dingUserId = this.dingDingService.getDingUserIdByAuthCode(authCode);
        if (null == dingUserId) {
            return ResultDTO.failure("invalidauthcode");
        }

        DingUser dingUser = this.dingUserRepository.findByDingUserId(dingUserId);
        if (null == dingUser) {
            dingUser = this.dingDingService.bind(dingUserId, userBean.getUsername());
        }

        final JwtAuthProvider jwtAuthProvider = new JwtAuthProvider(1000 * 24 * 60 * 60 * 1000, "secret");
        final String token = jwtAuthProvider.generateToken(dingUser.getUser().getUsername(),
                dingUser.getUser().getRoles().stream().map(b -> b.getCode()).collect(Collectors.toList()));

        return ResultDTO.success(token);
    }

    @ApiOperation("根据系统用户获取钉钉用户")
    @GetMapping("/systemuser/{username}/exchange")
    public ResultDTO<?> exchangeDingUser(@PathVariable final String username) {
        final String dingUserId = this.dingDingService.getDingUserIdBySystemUser(username);
        return ResultDTO.success(dingUserId);
    }

}
